package trie;

import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
class TrieNode implements ITrieNode {

	Object value; // richtiger Schl�ssel des Wortes; hier Char des Wortes als
					// Integer
	TrieNode parent; // elternknoten des aktuellen

	TreeMap<Comparable, TrieNode> partOfKeyToTrieNode; // TreeMap<Character
													// d.Wortes , Verweis
														// auf n�chsten Knoten>

	public TrieNode(TrieNode parent) {
		this.parent = parent;
		partOfKeyToTrieNode = new TreeMap<Comparable, TrieNode>();
	}

	/**
	 * Methode zum einstellen der Buchstaben in den Baum.
	 * 
	 * @param key
	 *            : It erator, in dem die Buchstaben des Wortes als Integer
	 *            hinterlegt sind
	 * @param value
	 *            : Schl�ssel des Gesamtwortes
	 * @return
	 */
	/*
	public Object recursiveInsert(Iterator key, Object value) {
		// iteratorDebug(key);		
		int current = (int) key.next();
		System.out.println("aktueller Char in ASCII: " + current);
		ITrieReference trieReference = null;

		boolean found = true;
		// gibt es keinen n�chsten Wert im Trie => aktuellen Wert versuchen
		// einzuf�gen
		if (!key.hasNext()) {
			this.value = value;

			// aktueller Key darf nicht in der Map enthalten sein => sont keine
			// Einf�gen
			if (!partOfKeyToTrieNode.containsKey(current)) {
				partOfKeyToTrieNode.put(current, new TrieNode(this));
				System.out.println("Char ist nicht im Baum. "
						+ "= > Es wird ein neuer Knoten erstellt.");
				found = false;
			}
			else {
				System.out.println("Char ist im Baum. => neuer Value des Wortes:"+value);
				if(this.value == null)
					found = false;
			}
			trieReference = (ITrieReference) new TrieReference(found, value);
			System.out.println("aktuelle Reference:: Found:"
					+ trieReference.getFound() + " val:"
					+ trieReference.getValue());
			System.out.println("letzter CHAR! Value=" + value + "\n\n");

		}
		// es gibt weitere Elemente im Trie
		while (key.hasNext()) {

			// aktueller Key darf nicht in der Map enthalten sein => sont keine
			// Einf�gen
			if (!partOfKeyToTrieNode.containsKey(current)) {
				partOfKeyToTrieNode.put(current, new TrieNode(this));
				System.out.println("Char ist nicht im Baum. "
						+ "= > Es wird ein neuer Knoten erstellt.");
				partOfKeyToTrieNode.get(current).recursiveInsert(key, value);
			} else {
				System.out
						.println("Char bereits im Baum. Rufe nächsten Node auf.");
				partOfKeyToTrieNode.get(current).recursiveInsert(key, value);
			}
		}

		return trieReference; // Muss ein ITrieReference zur�ckgeben!
	}
	*/
	
	//Neue insert
	public ITrieReference recursiveInsert(Iterator key , IActionAtInsert valueAddingStrategy){
		int current = (int) key.next();
		ITrieReference trieReference = null;
		boolean found = true;
		
		if (!key.hasNext()) {
			
			if (!partOfKeyToTrieNode.containsKey(current)) {
				partOfKeyToTrieNode.put(current, new TrieNode(this));
				System.out.println("Char ist nicht im Baum. "
						+ "= > Es wird ein neuer Knoten erstellt.");
			}
			
			if(value == null){
				this.value = valueAddingStrategy.actionInCaseOfNotFoundKey();
				System.out.println("Char ist im Baum. => neuer Value des Wortes:"+value);
				found=false;
			}
			else{
				this.value = valueAddingStrategy.actionInCaseOfFoundKey(value);
				found=true;
			}
			
			trieReference = (ITrieReference) new TrieReference(found, value);
			System.out.println("aktuelle Reference:: Found:"
					+ trieReference.getFound() + " val:"
					+ trieReference.getValue());
			System.out.println("letzter CHAR! Value=" + value + "\n\n");

		}
		// es gibt weitere Elemente im Trie
		while (key.hasNext()) {

			// aktueller Key darf nicht in der Map enthalten sein => sont keine
			// Einf�gen
			if (!partOfKeyToTrieNode.containsKey(current)) {
				partOfKeyToTrieNode.put(current, new TrieNode(this));
				System.out.println("Char ist nicht im Baum. "
						+ "= > Es wird ein neuer Knoten erstellt.");
				partOfKeyToTrieNode.get(current).recursiveInsert(key, valueAddingStrategy);
			} else {
				System.out
						.println("Char bereits im Baum. Rufe nächsten Node auf.");
				partOfKeyToTrieNode.get(current).recursiveInsert(key, valueAddingStrategy);
			}
		}
		
		
		
		
		return trieReference;
		
	}
	/**
	 * Methode zum debuggen des Iterators
	 * 
	 * @param key
	 *            :: Iterator der abgerufen wird
	 */
	void iteratorDebug(Iterator key) {
		while (key.hasNext()) {
			System.out.println("Suche nach: " + key.next());
		}
	}

	@Override
	public Object recursiveLookup(Iterator key) {
		int current = (int) key.next();	
		
		if(!key.hasNext()){
			if(this.value != null)
				return value;
			}
		
		while (key.hasNext()){		
			if(partOfKeyToTrieNode.containsKey(current)){
				partOfKeyToTrieNode.get(current).recursiveLookup(key);
			}
		}
		return null;
	}
	//Prüft ob schlüssel bereits im Baum eingetragen
	public boolean hasKey(Comparable value) {
		Set<Comparable> a = partOfKeyToTrieNode.keySet();
		Iterator it = a.iterator();
		if(recursiveLookup(it) != null)
			return true;
		else
			return false;
	}

	public String toString(int depth) {
		depth++;
		String temp = "";
		Set<Comparable> a = partOfKeyToTrieNode.keySet();
		Iterator it = a.iterator();
//		iteratorDebug(it);
		
		while(it.hasNext()){
			int ascii = (int)it.next();
			char ch = (char)ascii;
			for(int i=1;i<depth;i++){
				temp += ".";
			}
			temp += ch;
			if(this.value != null){
				temp += " --> " + value;
			}
			temp += "\n";
			temp +=	partOfKeyToTrieNode.get(ascii).toString(depth);

		}
		
		return temp;
	}
}
